const TAROT_CARDS = require('../models/TarotCard');
const { logInfo, logError } = require('../logger');

// 牌组定义
const DECK = TAROT_CARDS;

// 牌阵定义
const SPREADS = {
  daily: {
    name: '每日单张',
    card_count: 1,
    positions: ['今日主题']
  },
  three_cards: {
    name: '三张牌阵',
    card_count: 3,
    positions: ['过去', '现在', '未来']
  },
  celtic_cross: {
    name: '凯尔特十字',
    card_count: 10,
    positions: ['现状', '挑战', '基础', '过去', '目标', '未来', '自我', '环境', '希望', '结果']
  }
};

/**
 * 洗牌算法
 * @param {Array} deck - 塔罗牌组
 * @returns {Array} 洗牌后的牌组
 */
function shuffleDeck(deck) {
  try {
    const shuffled = [...deck];
    for (let i = shuffled.length - 1; i > 0; i--) {
      const j = Math.floor(Math.random() * (i + 1));
      [shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]];
    }
    logInfo('塔罗牌洗牌完成');
    return shuffled;
  } catch (error) {
    logError('塔罗牌洗牌失败', { error: error.message });
    throw error;
  }
}

/**
 * 塔罗牌服务
 */
const TarotService = {
  /**
   * 抽取塔罗牌
   * @param {number} count - 抽取牌的数量
   * @returns {Array} 抽取的塔罗牌数组
   */
  drawCards: (count) => {
    try {
      // 参数验证
      if (typeof count !== 'number' || count <= 0) {
        throw new Error('抽取牌数必须是正整数');
      }
      
      // 限制最大抽牌数
      const maxCards = Math.min(count, DECK.length);
      
      // 洗牌
      const shuffledDeck = shuffleDeck(DECK);
      
      // 抽取指定数量的牌
      const drawnCards = [];
      for (let i = 0; i < maxCards; i++) {
        // 随机决定正位还是逆位 (70% 正位, 30% 逆位)
        const isReversed = Math.random() < 0.3;
        
        // 创建牌的副本并添加位置和正逆位信息
        const card = { ...shuffledDeck[i] };
        card.position = i + 1;
        card.isReversed = isReversed;
        
        drawnCards.push(card);
      }
      
      logInfo('塔罗牌抽取完成', { count: drawnCards.length });
      return drawnCards;
    } catch (error) {
      logError('塔罗牌抽取失败', { error: error.message });
      throw error;
    }
  },
  
  /**
   * 生成牌阵位置解释
   * @param {string} position - 牌阵位置
   * @param {boolean} isReversed - 是否为逆位
   * @returns {string} 位置解释
   */
  getPositionMeaning: (position, isReversed) => {
    const positionMeanings = {
      '过去': isReversed ? '过去的影响被阻碍或逆转' : '过去的影响清晰可见',
      '现在': isReversed ? '当前状况存在阻碍或挑战' : '当前状况清晰明确',
      '未来': isReversed ? '未来发展可能遇到阻碍' : '未来发展积极向好',
      '现状': isReversed ? '当前状况存在隐藏的挑战' : '当前状况清晰明了',
      '挑战': isReversed ? '挑战可能被夸大或误解' : '面临的挑战明确具体',
      '基础': isReversed ? '基础不够稳固或存在隐患' : '基础坚实可靠',
      '目标': isReversed ? '目标可能需要重新审视' : '目标清晰可行',
      '自我': isReversed ? '自我认知可能存在偏差' : '自我认知清晰准确',
      '环境': isReversed ? '环境因素可能带来阻碍' : '环境因素有利',
      '希望': isReversed ? '希望可能需要重新定义' : '希望明确且可实现',
      '结果': isReversed ? '结果可能不如预期' : '结果积极正面',
      '今日主题': isReversed ? '今日主题需要谨慎对待' : '今日主题明确积极'
    };
    
    return positionMeanings[position] || (isReversed ? '逆位解读' : '正位解读');
  },
  
  /**
   * 解读单张塔罗牌
   * @param {Object} card - 塔罗牌对象
   * @param {string} position - 牌阵位置
   * @returns {Object} 解读结果
   */
  interpretSingleCard: (card, position = '') => {
    try {
      // 获取基础含义
      const baseMeaning = card.isReversed ? card.reversed : card.upright;
      
      // 获取位置含义
      const positionMeaning = TarotService.getPositionMeaning(position, card.isReversed);
      
      // 生成综合解读
      const interpretation = `${baseMeaning}。在"${position}"位置上，${positionMeaning}。`;
      
      return {
        card: card.name,
        position: position,
        meaning: baseMeaning,
        interpretation: interpretation,
        isReversed: card.isReversed
      };
    } catch (error) {
      logError('单张塔罗牌解读失败', { error: error.message, card: card.name });
      throw error;
    }
  },
  
  /**
   * 解读塔罗牌
   * @param {Array} cards - 塔罗牌数组
   * @returns {Object} 解读结果
   */
  interpretCards: (cards) => {
    try {
      // 参数验证
      if (!Array.isArray(cards) || cards.length === 0) {
        throw new Error('必须提供至少一张塔罗牌进行解读');
      }
      
      // 为每张牌生成解读
      const interpretations = cards.map((card, index) => {
        // 获取牌阵位置
        const position = SPREADS.three_cards.positions[index] || `位置${index + 1}`;
        return TarotService.interpretSingleCard(card, position);
      });
      
      // 生成整体解读
      let overallReading = '整体来看，';
      
      // 根据牌阵类型生成不同的整体解读
      if (cards.length === 1) {
        overallReading += '这张牌提示你关注当前的核心主题。';
      } else if (cards.length === 3) {
        overallReading += '过去的影响正在塑造现在的情况，而现在的选择将决定未来的发展方向。';
      } else if (cards.length === 10) {
        overallReading += '这是一个复杂的局面，需要综合考虑各个因素。当前状况、面临的挑战和基础条件都在影响着结果。';
      } else {
        overallReading += '这些牌共同描绘了你当前的情况和未来的可能性。';
      }
      
      // 添加积极建议
      overallReading += '建议你保持开放的心态，相信自己的直觉，并在做决定时充分考虑各方面的因素。';
      
      const reading = {
        cards: interpretations,
        overall: overallReading
      };
      
      logInfo('塔罗牌解读完成', { cardCount: cards.length });
      
      return reading;
    } catch (error) {
      logError('塔罗牌解读失败', { error: error.message });
      throw error;
    }
  },

  /**
   * 保存塔罗牌占卜记录
   * @param {string} userId - 用户ID
   * @param {string} spreadType - 牌阵类型
   * @param {string} question - 占卜问题
   * @param {string} category - 问题领域分类
   * @param {Array} cardsDrawn - 抽取的牌
   * @param {string} interpretation - 解读结果
   * @returns {Object} 保存的记录
   */
  saveReading: async (userId, spreadType, question, category, cardsDrawn, interpretation) => {
    try {
      // 创建新的占卜记录
      const TarotReading = require('../models/TarotReading');
      const reading = new TarotReading(
        userId, 
        spreadType, 
        question, 
        category, 
        cardsDrawn, 
        interpretation
      );
      
      // 保存记录
      const savedReading = reading.save();
      
      // 记录日志
      logInfo('Tarot reading saved', { 
        userId, 
        spreadType, 
        category,
        readingId: savedReading.id 
      });
      
      return savedReading.getDetails();
    } catch (error) {
      logError('Failed to save tarot reading', { 
        userId, 
        spreadType, 
        category,
        error: error.message 
      });
      throw error;
    }
  },

  /**
   * 收藏塔罗牌占卜记录
   * @param {number} readingId - 记录ID
   * @returns {Object} 更新后的记录
   */
  favoriteReading: async (readingId) => {
    try {
      const TarotReading = require('../models/TarotReading');
      const reading = TarotReading.getById(readingId);
      
      if (!reading) {
        throw new Error('Reading not found');
      }
      
      // 收藏记录
      const favoritedReading = reading.favorite();
      
      // 记录日志
      logInfo('Tarot reading favorited', { readingId });
      
      return favoritedReading.getDetails();
    } catch (error) {
      logError('Failed to favorite tarot reading', { 
        readingId, 
        error: error.message 
      });
      throw error;
    }
  },
  
  /**
   * 获取用户的占卜记录
   * @param {string} userId - 用户ID
   * @returns {Array} 用户的占卜记录列表
   */
  getUserReadings: async (userId) => {
    try {
      const TarotReading = require('../models/TarotReading');
      const readings = TarotReading.getByUserId(userId);
      
      // 记录日志
      logInfo('Retrieved user tarot readings', { userId, count: readings.length });
      
      return readings.map(reading => reading.getDetails());
    } catch (error) {
      logError('Failed to retrieve user tarot readings', { 
        userId, 
        error: error.message 
      });
      throw error;
    }
  },
  
  /**
   * 获取用户收藏的占卜记录
   * @param {string} userId - 用户ID
   * @returns {Array} 用户收藏的占卜记录列表
   */
  getSavedReadings: async (userId) => {
    try {
      const TarotReading = require('../models/TarotReading');
      const readings = TarotReading.getSavedReadings(userId);
      
      // 记录日志
      logInfo('Retrieved user saved tarot readings', { userId, count: readings.length });
      
      return readings.map(reading => reading.getDetails());
    } catch (error) {
      logError('Failed to retrieve user saved tarot readings', { 
        userId, 
        error: error.message 
      });
      throw error;
    }
  },

  /**
   * 获取今日推荐牌阵
   * 根据当前日期和用户ID生成个性化的牌阵推荐
   * @param {string} userId - 用户ID
   * @returns {Object} 推荐的牌阵信息
   */
  getDailyRecommendedSpread: (userId) => {
    try {
      // 获取当前日期
      const today = new Date();
      const dateKey = `${today.getFullYear()}-${today.getMonth() + 1}-${today.getDate()}`;
      
      // 生成基于日期和用户ID的哈希值来确定推荐牌阵
      const crypto = require('crypto');
      const hash = crypto.createHash('md5').update(`${userId}-${dateKey}`).digest('hex');
      
      // 根据哈希值选择牌阵类型
      const spreadKeys = Object.keys(SPREADS);
      const index = parseInt(hash.substring(0, 8), 16) % spreadKeys.length;
      const recommendedSpreadKey = spreadKeys[index];
      const recommendedSpread = SPREADS[recommendedSpreadKey];
      
      // 添加推荐理由
      const reasons = [
        "今天的能量场与这个牌阵完美契合",
        "这个牌阵能为你提供今日最重要的指引",
        "根据你的能量波动，这个牌阵最为适合",
        "宇宙能量提示你选择这个牌阵",
        "这个牌阵能揭示今日的关键信息"
      ];
      
      const reasonIndex = parseInt(hash.substring(8, 16), 16) % reasons.length;
      const recommendationReason = reasons[reasonIndex];
      
      const recommendation = {
        spreadType: recommendedSpreadKey,
        spreadName: recommendedSpread.name,
        cardCount: recommendedSpread.card_count,
        positions: recommendedSpread.positions,
        reason: recommendationReason,
        date: dateKey
      };
      
      logInfo('生成今日推荐牌阵', { userId, recommendedSpread: recommendedSpreadKey });
      
      return recommendation;
    } catch (error) {
      logError('生成今日推荐牌阵失败', { userId, error: error.message });
      throw error;
    }
  }
};

module.exports = TarotService;